package org.sk.gsync.app.utils.file;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.TimerTask;

import org.apache.log4j.Logger;
import org.sk.gsync.app.synch.DefaultSynchItem;
import org.sk.gsync.app.synch.SynchronizationManager;
import org.sk.gsync.app.utils.Tree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.google.gdata.util.ServiceException;

public class DirWatcher extends TimerTask {
    private String path;

    @Autowired
    @Qualifier("synchronizationManager")
    private SynchronizationManager synchronizationManager;

    private static final Logger LOGGER = Logger
        .getLogger(DirWatcher.class);

    @Override
    public final void run() {
        try {
            processFolder(path);
        } catch (IOException e) {
            LOGGER.error("IOException processing local folder.", e);
        } catch (ServiceException e) {
            LOGGER.error("ServiceException processing local folder.", e);
        }
    }

    public void processFolder(final String pathFolder)
            throws IOException, ServiceException {
        Tree<DefaultSynchItem<File>> tree =
            synchronizationManager.getLocalTree();
        HashSet checkedFiles = new HashSet();
        File[] filesArray = new File(pathFolder).listFiles();

        // scan the files and check for modification/addition
        for (int i = 0; i < filesArray.length; i++) {
            DefaultSynchItem<File> localFileItem =
                synchronizationManager.getLocalFileItem(filesArray[i]
                    .getAbsolutePath());
            checkedFiles.add(localFileItem);
            if (localFileItem == null) {
                DefaultSynchItem<File> parentLocalFile =
                    synchronizationManager.getLocalFileItem(filesArray[i]
                        .getParent());
                DefaultSynchItem<File> item = new DefaultSynchItem<File>();
                item.setEmbeddedObject(filesArray[i]);
                item.setLevel(parentLocalFile.getLevel() + 1);
                item.setParent(parentLocalFile);
                item.setTitle(filesArray[i].getName());
                tree.getTree(parentLocalFile).addLeaf(item);
                LOGGER.info("[ADDED] file: "
                    + filesArray[i].getAbsolutePath());
                // onChange(filesArray[i], "add");
            } else if (localFileItem.getEmbeddedObject().lastModified() != filesArray[i]
                .lastModified()) {
                localFileItem.setEmbeddedObject(filesArray[i]);
                LOGGER.info("[MODIFIED] file: "
                    + filesArray[i].getAbsolutePath());
            }
            if (filesArray[i].isDirectory()) {
                processFolder(filesArray[i].getAbsolutePath());
            }
        }

        // now check for deleted files
        Collection<DefaultSynchItem<File>> successors =
            tree.getSuccessors(synchronizationManager
                .getLocalFileItem(pathFolder));
        successors.removeAll(checkedFiles);
        Iterator it = successors.iterator();
        while (it.hasNext()) {
            DefaultSynchItem<File> deletedFile =
                (DefaultSynchItem<File>) it.next();
            LOGGER.info("[DELETED] file: "
                + deletedFile.getEmbeddedObject().getAbsolutePath());
            deletedFile.setEmbeddedObject(null);
        }
        synchronizationManager.createOperations();
    }

    /**
     * @param path
     *            The path to set.
     */
    public void setPath(final String path) {
        this.path = path;
    }
}
